UNIT UText;
{$SETC IsIntrinsic := TRUE }

{$IFC IsIntrinsic}
INTRINSIC;
{$ENDC}


{Multiple Paragraph Building Block for the Tool Kit}

{changed 04/25/84 1437  Added TTextImage.TxtImgForClipBoard method}
{changed 04/18/84 1652  Added firstLinePixel, useFirstPixel fields to TTextImage}
{changed 04/16/84 1135  Added styleSheet field to TParaFormat}
{changed 04/13/84 0209  Added TTextImage.NewEditPara}
{changed 04/12/84 2344  Changed parameter list of TParagraph.UpdateRuns}
{changed 04/10/84 1400  Changed TEditPara.images field back to a TList}

INTERFACE
{$DECL fUseUnivText}
{$SETC fUseUnivText := TRUE}

USES
    {$U libtk/UObject}		  UObject,
{$IFC LibraryVersion <= 20}
    {$U UFont}		    UFont,
{$ENDC}
    {$U QuickDraw}	    QuickDraw,
    {$U libtk/UDraw}		  UDraw,
{$IFC fUseUnivText}
    {$U libtk/UUnivText}	  UTKUniversalText,
{$ENDC}
    {$U UABC}		    UABC;

{$DECL fTextTrace}
{$SETC fTextTrace := fDbgOK}
{$DECL fParaTrace}
{$SETC fParaTrace := fDbgOK}
{$DECL fRngText}
{$SETC fRngText := fDbgOK}

CONST

    cVertMargin = 4;
    cHorizMargin = 6;

    somethingKind = 1;

TYPE

    TStyleChange = RECORD
        lp:	    INTEGER;
        newStyle:   TTypeStyle;
        END;

    TTxtTabDescriptor = RECORD
        xCoord:	    INTEGER;
        quad:	    TAlignment;
        {MORE LATER}
        END;

    TDrawAction = (actionDraw, actionInval, actionNone);

{ PARAGRAPH SUBCLASSES }

    TParaFormat = SUBCLASS OF TObject
        dfltTStyle:	    TTypeStyle;	     {default type style}
        wordWrap:	    BOOLEAN;
        quad:		    TAlignment;
        firstIndent:	    INTEGER;
        leftIndent:	    INTEGER;
        rightIndent:	    INTEGER;
        spaceAbovePara:	    INTEGER;
        spaceBelowPara:	    INTEGER;
        lineSpacing:	    INTEGER;
        tabs:		    TArray;

        refCount:	    INTEGER;	    {number of paragraphs referencing this paraFormat}
        permanent:	    BOOLEAN;	    {TRUE -> don't free when refcount goes to zero}
        styleSheet:	    TStyleSheet;    {NIL if format not in a styleSheet}

        FUNCTION TParaFormat.CREATE(object: TObject; heap: THeap; itsStyleSheet: TStyleSheet): TParaFormat;
        {$IFC fParaTrace}
        PROCEDURE TParaFormat.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}
        PROCEDURE TParaFormat.SetTypeStyle(tStyle: TTypeStyle);
        PROCEDURE TParaFormat.ChangeRefCountBy(delta: INTEGER);
        END;

    TParagraph = SUBCLASS OF TString
        typeStyles:     TArray; { of TStyleChange }

      {Creation/Destruction}
        FUNCTION  TParagraph.CREATE(object: TObject; heap: THeap;
                                        initialSize: INTEGER; initialTypeStyle: TTypeStyle): TParagraph;
        PROCEDURE TParagraph.Free; OVERRIDE;

      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE  TParagraph.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

      {Overridden TString methods}
        PROCEDURE TParagraph.Draw(i: LONGINT; howMany: INTEGER); OVERRIDE;
        FUNCTION  TParagraph.Width(i: LONGINT; howMany: INTEGER): INTEGER; OVERRIDE;

      {This method is used by TParagraph.Draw and TParagraph.Width to interpret the typeStyles array}
        PROCEDURE TParagraph.DrawLine(startLP, endLP: INTEGER; fDraw: BOOLEAN; fWidth: BOOLEAN;
                                             VAR width: INTEGER; VAR styleIndex: INTEGER);

      {Type Style Maintainence}
        PROCEDURE TParagraph.ChangeStyle(startLP, endLP: INTEGER; PROCEDURE Change(VAR typeStyle: TTypeStyle);
                                                        VAR styleOfStartLP: TTypeStyle);


        {These four routines all call ChangeStyle}
        PROCEDURE TParagraph.ChgFace(startLP, endLP: INTEGER;
                                        newOnFaces: {$IFC LibraryVersion <= 20}TSeteface{$ELSEC}Style{$ENDC};
                                                        VAR styleOfStartLP: TTypeStyle);
        PROCEDURE TParagraph.ChgFontSize(startLP, endLP: INTEGER; newFontSize: Byte;
                                                        VAR styleOfStartLP: TTypeStyle);
        PROCEDURE TParagraph.ChgFontFamily(startLP, endLP: INTEGER; newFontFamily: Byte;
                                                        VAR styleOfStartLP: TTypeStyle);
        PROCEDURE TParagraph.NewStyle(startLP, endLP: INTEGER; newTypeStyle: TTypeStyle);

        PROCEDURE TParagraph.CleanRuns;
        PROCEDURE TParagraph.UpdateRuns(atLP: INTEGER; replacedChars: INTEGER; insertedChars: INTEGER);

      {Character Maintainence}
        PROCEDURE TParagraph.ReplPara(fPos, numChars: INTEGER;
                                            otherPara: TParagraph; otherFPos, otherNumChars: INTEGER);
        PROCEDURE TParagraph.ReplTString(fPos, numChars: INTEGER;
                                            otherString: TString; otherFPos, otherNumChars: INTEGER);
        PROCEDURE TParagraph.ReplPString(fPos, numChars: INTEGER; pStr: TPString);
      {Utilities}
      {BuildExtentLRect takes an LPoint that indicates the baseline of the paragraph.  It returns
       in extentLRect the bounding rectangle whose height is based on the tallest font in the
       paragraph and width is the width of the characters in the paragraph. Specifically:
                        top    := baseLPt.v - tallestFontInfo.ascent;
                        bottom := baseLPt.v + tallestFontInfo.descent + tallestFontInfo.leading;
                        left   := baseLPt.h;
                        right  := baseLpt.h + paragraph.Width;}
        PROCEDURE TParagraph.BuildExtentLRect(baseLPt: LPoint; VAR extentLRect: LRect);
        FUNCTION  TParagraph.FixLP(LP: INTEGER): INTEGER;
        PROCEDURE TParagraph.SetTypeStyle(tStyle: TTypeStyle);
        PROCEDURE TParagraph.StyleAt(lp: INTEGER; VAR typeStyle: TTypeStyle);

      {Word Selection}
        PROCEDURE TParagraph.FindWordBounds(orig: INTEGER; VAR first, last: INTEGER);
        FUNCTION  TParagraph.Qualifies(pos: INTEGER): BOOLEAN;

        END;


   {Editable Paragraph}
    TEditPara = SUBCLASS OF TParagraph
      { character stuff }
        bsCount:        INTEGER;
      { formatting stuff }
        nestLevel:      INTEGER;
        format:	        TParaFormat;

      { paraImage stuff }
        beingFiltered:  BOOLEAN;    { TRUE when a type style command has just been
                                      performed on this paragraph}

        (*
        maxImage:       INTEGER;
        numImages:      INTEGER;
        images:	        ARRAY [1..1] OF TParaImage;  {THIS MUST BE LAST FIELD !}
        *)
        images:	        TList;	    { Users may subclass TEditPara }

      {Creation/Destruction}
        FUNCTION  TEditPara.CREATE(object: TObject; heap: THeap; initialSize: INTEGER;
                                        itsFormat: TParaFormat): TEditPara;
        PROCEDURE TEditPara.Free; OVERRIDE;

      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE TEditPara.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

      {Special Editing}
        PROCEDURE TEditPara.BeginInsertion(atLP: INTEGER; size:INTEGER);
        PROCEDURE TEditPara.EndInsertion;
        FUNCTION  TEditPara.GrowSize: INTEGER;
        PROCEDURE TEditPara.InsertOneChar(ch: CHAR; atLP: INTEGER);

      {Utility}
        PROCEDURE TEditPara.SetTypeStyle(tStyle: TTypeStyle); OVERRIDE;

      {ParaImage Maintenance}
        PROCEDURE TEditPara.EachImage(PROCEDURE ImageProc(paraImage: TParaImage));
        PROCEDURE TEditPara.DelImage(delImage: TParaImage; fFree: BOOLEAN);
        PROCEDURE TEditPara.InsImage(paraImage: TParaImage);
        PROCEDURE TEditPara.DelImgIF(FUNCTION ShouldDelete(paraImage: TParaImage): BOOLEAN);
        END;


    TLineInfo = SUBCLASS OF TObject
        valid:	        BOOLEAN;
        startLP:        INTEGER;
        lastDrawnLP:    INTEGER;  {last character in line to draw: may omit trailing spaces}
        endLP:	        INTEGER;  {last character in line: equals next lineInfo.startLP - 1}
        lineLRect:      LRect;
        lineAscent:     INTEGER;

        FUNCTION  TLineInfo.CREATE(object: TObject; heap: THeap): TLineInfo;
        {$IFC fParaTrace}
        PROCEDURE TLineInfo.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

      {Used by subclassers who don't like the way the hilite/update
       rectangle is chosen so they can overrride it}
        FUNCTION TLineInfo.LeftCoord(proposedLeftPixel: LONGINT): LONGINT;
        FUNCTION TLineInfo.RightCoord(proposedRightPixel: LONGINT): LONGINT;
        END;


    TParaImage = SUBCLASS OF TImage
        paragraph:      TEditPara;
        height:	        INTEGER;    { pixel height of the paragraph}

        lineList:       TList;	    { of TLineInfo}
        changed:        BOOLEAN;
        tickCount:      INTEGER;    { incremented (mod MAXINT) every time image is drawn }
        startLP:        INTEGER;
        endLP:	        INTEGER;    { while drawing, this is the LP of the beginning of the next line
                                      which, when drawing is finished, may be in another image if the
                                      paragraph is split }
        textImage:      TTextImage; { the textImage that this image belongs to }
        wasOffset:      BOOLEAN;    { used by Building block to determine when to invalidate}

      {Creation}
        FUNCTION  TParaImage.CREATE(object: TObject; heap: THeap; itsView: TView;
                                        itsParagraph: TEditPara; itsLRect: LRect;
                                        lineTop: LONGINT; lineLeft: LONGINT): TParaImage;
        PROCEDURE TParaImage.Free; OVERRIDE;

      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE TParaImage.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

      {Routines}
        PROCEDURE TParaImage.ComputeLineInfo(curLine: TLineInfo; maxLineLen: INTEGER;
                                                VAR nextLP: INTEGER; VAR lRectNeeded: LRect);
        FUNCTION  TParaImage.DfltLineInfo(lineTop: LONGINT; lineLeft: LONGINT): TLineInfo;
        PROCEDURE TParaImage.DrawLine(startLP: INTEGER; fDraw: BOOLEAN;
                                            stopWidth, wrapWidth: INTEGER;
                                            VAR lineWidth, lastToDraw, endLP: INTEGER);
        PROCEDURE TParaImage.DrawParaImage(limitLRect: LRect; startLP: INTEGER; drawAction: TDrawAction;
                                                invalBits: BOOLEAN; VAR drawnLRect: LRect);
        PROCEDURE TParaImage.Draw; OVERRIDE;
        PROCEDURE TParaImage.FastDrawLine(startLP, endLP: INTEGER; fDraw: BOOLEAN; fWidth: BOOLEAN;
                                             VAR width: INTEGER; VAR styleIndex: INTEGER);
        FUNCTION  TParaImage.GetFormat: TParaFormat;
        PROCEDURE TParaImage.LineWithLPt(pt: LPoint; VAR lineIndex: INTEGER; VAR lineInfo: TLineInfo);
        PROCEDURE TParaImage.LocateLP(LP: INTEGER; VAR lineIndex: INTEGER; VAR pixel: LONGINT);
        FUNCTION  TParaImage.LpWithLPt(pt: LPoint): INTEGER;
        PROCEDURE TParaImage.OffSetBy(deltaLPt: LPoint); OVERRIDE;
        FUNCTION  TParaImage.ParaTextWidth(startLP, endLP: INTEGER): INTEGER;
        PROCEDURE TParaImage.RedrawLines(startLine: INTEGER; endLine: INTEGER);
        FUNCTION  TParaImage.SeesSameAs(image: TImage): BOOLEAN; OVERRIDE;

       {validation/invalidation procs}
        PROCEDURE TParaImage.InvalLinesWith(startLP, endLP: INTEGER);
        PROCEDURE TParaImage.AdjustLineLPs(atLP, deltaLP: INTEGER);
        END;



{ MULTI-PARAGRAPH SUBCLASSES }

    TStyleSheet = SUBCLASS OF TObject
        formats:    TList; {of TParaFormat}

      {Creation}
        FUNCTION  TStyleSheet.CREATE(object: TObject; heap: THeap): TStyleSheet;
        PROCEDURE TStyleSheet.Free; OVERRIDE;

      {Installs Default paraFormat into formats list}
        PROCEDURE TStyleSheet.InitDefault;
      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE TStyleSheet.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}
        END;

    TTextRange = SUBCLASS OF TObject
        firstPara:  TEditPara;
        firstIndex: LONGINT;
        firstLP:    INTEGER;
        lastPara:   TEditPara;
        lastIndex:  LONGINT;
        lastLP:	    INTEGER;

      {Creation}
        FUNCTION  TTextRange.CREATE(object: TObject; heap: THeap;
                                        beginPara: TEditPara; beginIndex: LONGINT; beginLP: INTEGER;
                                        endPara: TEditPara; endIndex: LONGINT; endLP: INTEGER): TTextRange;

      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE TTextRange.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

      {AdjustBy adjust the fields of TTextRange by the value of delta (where delta is in LPs)}
        PROCEDURE TTextRange.AdjustBy(delta: INTEGER);
        END;

    TText = SUBCLASS OF TObject
        paragraphs: TList;  {of TEditPara }
        styleSheet: TStyleSheet;

        txtImgList: TList;  {of TTextImages that point to this text;
                             IMPORTANT: If the multiple linked textImage feature is used as described in
                                        TTextImage below, the application should only store the
                                        head text image in this list.  This list is intended for
                                        textImages that are viewing the same text object independently
                                        (ie in different panels)}

      {Creation/Freeing}
        FUNCTION  TText.CREATE(object: TObject; heap: THeap; itsStyleSheet: TStyleSheet): TText;

        {DfltTextImage can be called after CREATE to create and return a single textImage. It also
         creates one empty paragraph using the first paraFormat in SELF.styleSheet.  It installs the
         textImage in txtImgList and the paragraph in paragraphs.  This routine calls
         textImage.RecomputeImages to set up the first paraImage.}
        FUNCTION  TText.DfltTextImage(view: TView; imageLRect: LRect; imgIsGrowable: BOOLEAN): TTextImage;

       {TText.Free frees all paragraphs that belong to this text object and all textImages that
        reference this text object}
        PROCEDURE TText.Free; OVERRIDE;
        PROCEDURE TText.FreeSelf(freeParas: BOOLEAN);
      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE  TText.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

       {Calls to textImage procs get routed through these}
        PROCEDURE TText.ChangeSelInOtherPanels(textSelection: TTextSelection);
        PROCEDURE TText.DelPara(delPara: TEditPara;  fFree: BOOLEAN);
        PROCEDURE TText.Draw;
        PROCEDURE TText.HiliteRange(highTransit: THighTransit; textRange: TTextRange; wholePara: BOOLEAN);
        PROCEDURE TText.HiliteParagraphs(highTransit: THighTransit;
                                                startIndex: LONGINT; startLP: INTEGER;
                                                endIndex: LONGINT; endLP: INTEGER; wholePara: BOOLEAN);
        PROCEDURE TText.InsParaAfter(existingPara: TEditPara;  newPara: TEditPara);
        PROCEDURE TText.Invalidate;
        PROCEDURE TText.MarkChanged(textRange: TTextRange);
        PROCEDURE TText.RecomputeImages;
        FUNCTION  TText.SelectAll(textImage: TTextImage): TTextSelection;
        END;



    TTextImage = SUBCLASS OF TImage
        text:		    TText;      {complete list of paragraphs}
        imageList:	    TList;      {paraImages for some range of paragraphs in text}
        tickCount:	    INTEGER;
        growsDynamically:   BOOLEAN;    {TRUE -->  extentLRect bottom grows as more text entered;
                                         FALSE ->  text is truncated at last line that fits}
        minHeight:	    INTEGER;    {the minimum height to shrink (if growsDynamically=TRUE);
                                         defaults to height of original extentLRect}

        formerBottom:	    LONGINT;    {Used by Invalidate when the displayed paragraphs get shorter
                                         and text at end needs to be erased}
        updateLRect:	    LRect;      { "	    "			    "		    "}

        firstLinePixel:	    LONGINT;    {Used by Text BB to limit what gets erased on first update line}
        useFirstPixel:	    BOOLEAN;


        { The following fields support multiple linked text images displaying a single text object,
          where the text "flows" from one box to the next.  APPLICATIONS ARE RESPONSIBLE FOR
          MAINTAINING THESE FIELDS.  This Building Block uses these fields for drawing, etc.
          All text images in a chain should have growsDynamically set to FALSE (except possibly
          for the last text image in a chain).
          For applications that DO NOT use this feature, the fields will always be as follows:
                startLP = 0;
                endLP =	  LP of last character in last paragraph; (if growsDynamically = TRUE)
                          LP of last character that fit in extentLRect; (if growsDynamically = FALSE)
                prevTxtImg, nextTxtImg = NIL;
                headTxtImg = SELF;
                tailTxtImg = SELF;
         }
        firstIndex:     LONGINT;    {index of paragraph at SELF.imageList.First}
        startLP:        INTEGER;    {startLP of paragraph at SELF.imageList.First}
        endLP:	        INTEGER;    {endLP of paragraph at SELF.imageList.Last}

        prevTxtImg:     TTextImage; {  for linking textImages that display different parts of }
        nextTxtImg:     TTextImage; {  the same text object. eg: columns}
        headTxtImg:     TTextImage; {points to first text image in this list}
        tailTxtImg:     TTextImage; {points to last text image in this list}

      {Creation}
        FUNCTION  TTextImage.CREATE(object: TObject; heap: THeap; itsView: TView;
                                        itsLRect: LRect; itsText: TText; isGrowable: BOOLEAN): TTextImage;

        {TTextImage.Free frees all text images and their paraImages in the text image chain.
         It does NOT free any paragraphs, text objects, or paraFormats.	 Call this only once
         for each text image chain (NOT for each text image in the chain).  Note that TText.Free
         frees its textImages so calling this routine is not necessary in most cases}
        PROCEDURE  TTextImage.Free; OVERRIDE;

        {TTextImage.FreeOneTextImage frees just one text image from the chain.  It pays no attention
         to links or whether this is the head text image.  Maintenance of these fields  must be
         handled by the caller before calling this routine.  Those who do not use linked text images
         should always call TTextImage.Free above, NOT this routine}
        PROCEDURE TTextImage.FreeOneTextImage;

      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE TTextImage.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

      {Drawing}
        PROCEDURE TTextImage.Draw; OVERRIDE;
        PROCEDURE TTextImage.DrawImages(fDraw: BOOLEAN);
        PROCEDURE TTextImage.DrawOrInval(invalBits: BOOLEAN);
        PROCEDURE TTextImage.HiliteText(highTransit: THighTransit;
                                            startIndex: LONGINT; startLP: INTEGER;
                                            endIndex: LONGINT; endLP: INTEGER; wholePara: BOOLEAN);

      {Locating}
        PROCEDURE TTextImage.FindParaAndLp(LPt: LPoint; VAR paraImage: TParaImage;
                                                          VAR paraIndex: LONGINT; VAR aLP: INTEGER);
        FUNCTION  TTextImage.FindTextImage(VAR mouseLPt: LPoint; VAR firstTxtImg: TTextImage): TTextImage;
        FUNCTION  TTextImage.ImageBottom: LONGINT;
        PROCEDURE TTextImage.GetImageRange(firstIndex: LONGINT; VAR firstLP: INTEGER;
                                             lastIndex:	 LONGINT; VAR lastLP:  INTEGER;
                                             VAR firstImage, lastImage: TParaImage);
        FUNCTION  TTextImage.ImageWith(paragraph: TEditPara; lp: INTEGER): TParaImage;
        PROCEDURE TTextImage.MousePress(mouseLPt: LPoint); OVERRIDE;
        PROCEDURE TTextImage.OffsetBy(deltaLPt: LPoint); OVERRIDE;

      {Image maintenence}
        PROCEDURE TTextImage.AddImage(paraImage: TParaImage);
        PROCEDURE TTextImage.DelImagesWith(delPara: TEditPara);
        PROCEDURE TTextImage.InsertNewPara(existingPara, newPara: TEditPara);
        PROCEDURE TTextImage.InvalAll;
        PROCEDURE TTextImage.Invalidate; OVERRIDE; {Invalidate changed lineLRects in changed paraimages}
        PROCEDURE TTextImage.MarkChanged(startIndex: LONGINT; startLP: INTEGER;
                                            endIndex: LONGINT; endLP: INTEGER);
        FUNCTION  TTextImage.NewTextSelection(firstPara: TEditPara; firstIndex: LONGINT; firstLP: INTEGER;
                                            lastPara: TEditPara; lastIndex: LONGINT; lastLP: INTEGER
                                            ): TTextSelection;
        PROCEDURE TTextImage.RecomputeImages(drawAction: TDrawAction; invalBits: BOOLEAN);
        PROCEDURE TTextImage.Resize(newExtent: LRect); OVERRIDE;
        FUNCTION  TTextImage.SeesSameAs(image: TImage): BOOLEAN; OVERRIDE;

      {By default SetFirstIndex just sets firstIndex to	 0, but subclassers may override this
       if they want the display to start from other than the first paragraph}
        PROCEDURE TTextImage.SetFirstIndex;

        {These routines are provided so that users can subclass the appropriate class and
         then override these methods so that the building block will create the user's subclass
         when generating new instances of that class. }
        FUNCTION  TTextImage.NewEditPara(initialSize: INTEGER; itsFormat: TParaFormat): TEditPara;
        FUNCTION  TTextImage.NewParaImage(itsParagraph: TEditPara; itsLRect: LRect;
                                        lineTop: LONGINT; lineLeft: LONGINT): TParaImage;
        FUNCTION  TTextImage.NewTextImage(heap: THeap; itsView: TView; itsLRect: LRect;
                                                itsText:TText; isGrowable: BOOLEAN): TTextImage;
        FUNCTION  TTextImage.TxtImgForClipBoard(heap: THeap; itsView: TView; itsLRect: LRect;
                                                itsText:TText; isGrowable: BOOLEAN): TTextImage;
        END;


    {Clipboard Text View}
    TTextView = SUBCLASS OF TView
        textImage:  TTextImage;
        valid:	    BOOLEAN;	   {If FALSE, calls Recompute before Drawing}

      {Creation}
        FUNCTION  TTextView.CREATE(object: TObject; heap: THeap; itsPanel: TPanel; itsExtent: LRect)
                                  : TTextView;

      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE TTextView.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

        {$IFC fUseUnivText}
        PROCEDURE TTextView.CreateUniversalText; OVERRIDE;
        {$ENDC}
        PROCEDURE TTextView.Draw; OVERRIDE;
        PROCEDURE TTextView.MousePress(mouseLPt: LPoint); OVERRIDE;
        END;


    {$IFC fUseUnivText}
    TTextWriteUnivText = SUBCLASS OF TTKWriteUnivText
        textSelection:  TTextSelection;
        currIndex:      LONGINT;
        currPara:       TEditPara;
        currLP:	        INTEGER;
        currStyleIndex: INTEGER;
        currTStyles:	 TArray;
      {Creation}
        FUNCTION  TTextWriteUnivText.CREATE(object: TObject; heap: THeap;
                                                itsString: TString; itsDataSize: INTEGER;
                                                itsTextSel: TTextSelection): TTextWriteUnivText;

      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE TTextWriteUnivText.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

        PROCEDURE TTextWriteUnivText.FillParagraph; OVERRIDE;
        END;
    {$ENDC}


    TTextSelection = SUBCLASS OF TSelection
        textImage:	    TTextImage;
        textRange:	    TTextRange;
        isWordSelection:    BOOLEAN;
        isParaSelection:    BOOLEAN;
        viewTick:	    INTEGER;
        amTyping:	    BOOLEAN;
        currTypeStyle:	    TTypeStyle;

        FUNCTION  TTextSelection.CREATE(object: TObject; heap: THeap; itsView: TView;
                                            itsTextImage: TTextImage; itsAnchorLPt: LPoint;
                                            beginPara: TEditPara; beginIndex: LONGINT; beginLP: INTEGER;
                                            endPara: TEditPara; endIndex: LONGINT; endLP: INTEGER
                                            ): TTextSelection;


      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE TTextSelection.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

      {Commands}
        PROCEDURE TTextSelection.KeyText;
        FUNCTION  TTextSelection.NewCommand(cmdNumber: TCmdNumber): TCommand; OVERRIDE;
        FUNCTION  TTextSelection.NewStyleCmd(heap: THeap; cmdNumber: TCmdNumber;
                                    textImage: TTextImage): TCommand;
        FUNCTION  TTextSelection.NewCutCopyCmd(heap: THeap; cmdNumber: TCmdNumber;
                                    textImage: TTextImage): TCommand; DEFAULT;
        PROCEDURE TTextSelection.StyleFromContext; DEFAULT;
        PROCEDURE TTextSelection.DoChangeStyle(cmdNumber: TCmdNumber; paragraph: TParagraph;
                                        firstLP: INTEGER; lastLP: INTEGER; VAR newStyle: TTypeStyle);
        PROCEDURE TTextSelection.ChangeStyle(cmdNumber: TCmdNumber); DEFAULT;
      {Editing}
        PROCEDURE TTextSelection.ChangeText(PROCEDURE TextEdit; PROCEDURE Adjust); DEFAULT;
        FUNCTION  TTextSelection.CopySelf(heap: THeap; view: TView): TMultiParaSelection; DEFAULT;
        PROCEDURE TTextSelection.CutCopy(clipSelection: TSelection; deleteOriginal: BOOLEAN); DEFAULT;
        PROCEDURE TTextSelection.DeleteAndFree; DEFAULT;
        FUNCTION  TTextSelection.DeleteButSave: TText; DEFAULT;

      {Highlighting}
        PROCEDURE TTextSelection.Highlight(highTransit: THighTransit); OVERRIDE;

      {Selecting}
        FUNCTION  TTextSelection.BecomeInsertionPoint: TInsertionPoint;
        PROCEDURE TTextSelection.GetHysteresis(VAR hysterPt: Point); OVERRIDE;
        PROCEDURE TTextSelection.MousePress(mouseLPt: LPoint); OVERRIDE;
        FUNCTION  TTextSelection.SelSize: INTEGER; ABSTRACT;

      {Invalidation}
        PROCEDURE TTextSelection.Invalidate; DEFAULT;

      {Generate Text Selection in another panel (ie. another Text Image)}
        FUNCTION  TTextSelection.ReplicateForOtherPanel(itsTextImage: TTextImage): TTextSelection;
        END;


    TInsertionPoint = SUBCLASS OF TTextSelection
        typingCmd:	    TTypingCmd;	    {the current typing command (if user is typing)}
        styleCmdNumber:	    INTEGER;	    {Set to cmdNumber when a type style item is chosen,
                                                set to zero otherwise}
        newestLP:	    INTEGER;	    {the lp position as updated between KeyPause's}
        justReturned:	    BOOLEAN;	    {flag that prevents redundant update in KeyPause}

        nextHighTransit:    THighTransit;
        nextTransitTime:    LONGINT;

      {Creation/Freeing}
        FUNCTION  TInsertionPoint.CREATE(object: TObject; heap: THeap; itsView: TView;
                                      itsTextImage: TTextImage; itsAnchorLPt: LPoint; itsParagraph: TEditPara;
                                      itsIndex: LONGINT; itsLP: INTEGER): TInsertionPoint;

      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE TInsertionPoint.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

      {Commands}
        PROCEDURE TInsertionPoint.IdleBegin(centiSeconds: LONGINT); OVERRIDE;
        PROCEDURE TInsertionPoint.IdleContinue(centiSeconds: LONGINT); OVERRIDE;
        PROCEDURE TInsertionPoint.IdleEnd(centiSeconds: LONGINT); OVERRIDE;
        FUNCTION  TInsertionPoint.NewCutCopyCmd(heap: THeap; cmdNumber: TCmdNumber;
                                    textImage: TTextImage): TCommand; OVERRIDE;
        PROCEDURE TInsertionPoint.StyleFromContext; OVERRIDE;

      {Editing}
        PROCEDURE TInsertionPoint.CutCopy(clipSelection: TSelection; deleteOriginal: BOOLEAN); OVERRIDE;
        PROCEDURE TInsertionPoint.FinishPaste(clipSelection: TSelection; pic: PicHandle);
        PROCEDURE TInsertionPoint.InsertText(text: TText; isParaSelection: BOOLEAN; isWordSelection: BOOLEAN;
                                                                                    universalText: BOOLEAN);
        PROCEDURE TInsertionPoint.KeyBack(fWord: BOOLEAN); OVERRIDE;
        PROCEDURE TInsertionPoint.KeyChar(ch: CHAR); OVERRIDE;
        PROCEDURE TInsertionPoint.KeyClear; OVERRIDE;
        PROCEDURE TInsertionPoint.KeyForward(fWord: BOOLEAN); OVERRIDE;

      {Selecting}
        PROCEDURE TInsertionPoint.MouseMove(mouseLPt: LPoint); OVERRIDE;
        PROCEDURE TInsertionPoint.MousePress(mouseLPt: LPoint); OVERRIDE;
        PROCEDURE TInsertionPoint.MouseRelease; OVERRIDE;

        END;


    TOneParaSelection = SUBCLASS OF TTextSelection
        anchorBegin:    INTEGER;
        anchorEnd:      INTEGER;    {anchorBegin <> anchorEnd iff double or triple click}

      {Creation/Freeing}
        FUNCTION  TOneParaSelection.CREATE(object: TObject; heap: THeap; itsView: TView;
                                     itsTextImage:  TTextImage; itsAnchorLPt: LPoint; itsParagraph: TEditPara;
                                     itsIndex: LONGINT; oldLP: INTEGER; currLP: INTEGER): TOneParaSelection;

      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE TOneParaSelection.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

      {Commands}
        PROCEDURE TOneParaSelection.StyleFromContext; OVERRIDE;

      {Editing}
        FUNCTION  TOneParaSelection.CopySelf(heap: THeap; view: TView): TMultiParaSelection; OVERRIDE;
        PROCEDURE TOneParaSelection.DeleteAndFree; OVERRIDE;
        FUNCTION  TOneParaSelection.DeleteButSave: TText; OVERRIDE;

      {Selecting}
        PROCEDURE TOneParaSelection.MouseMove(mouseLPt: LPoint); OVERRIDE;
        PROCEDURE TOneParaSelection.MouseRelease; OVERRIDE;

        END;


    TMultiParaSelection = SUBCLASS OF TTextSelection
        anchorPara:     TEditPara;
        anchorIndex:    LONGINT;
        anchorBegin:    INTEGER;
        anchorEnd:      INTEGER;    {anchorBegin <> anchorEnd iff double or triple click}

      {Creation/Freeing}
        FUNCTION  TMultiParaSelection.CREATE(object: TObject; heap: THeap; itsView: TView;
                                            itsTextImage: TTextImage; itsAnchorLPt: LPoint;
                                            beginPara: TEditPara; beginIndex: LONGINT; beginLP: INTEGER;
                                            endPara: TEditPara; endIndex: LONGINT; endLP: INTEGER;
                                            beginIsAnchor: BOOLEAN): TMultiParaSelection;

      {Debugging}
        {$IFC fParaTrace}
        PROCEDURE TMultiParaSelection.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}

      {Commands}
        PROCEDURE TMultiParaSelection.StyleFromContext; OVERRIDE;

      {Editing}
        FUNCTION  TMultiParaSelection.CopySelf(heap: THeap; view: TView): TMultiParaSelection; OVERRIDE;
        FUNCTION  TMultiParaSelection.Delete(saveIt: BOOLEAN): TText;
        PROCEDURE TMultiParaSelection.DeleteAndFree; OVERRIDE;
        FUNCTION  TMultiParaSelection.DeleteButSave: TText; OVERRIDE;

      {Selecting}
        PROCEDURE TMultiParaSelection.MouseMove(mouseLPt: LPoint); OVERRIDE;
        PROCEDURE TMultiParaSelection.MouseRelease; OVERRIDE;

        END;


                        {-------------  COMMANDS  -----------------}

    TClearTextCmd = SUBCLASS OF TCommand

      {Variables}
        savedText:      TText;	    {save the cleared text for undo}
        text:	        TText;	    {the text object we are clearing}

      {Creation}
        FUNCTION  {TClearTextCmd.}CREATE(object: TObject; heap: THeap; itsCmdNumber: TCmdNumber;
                                         itsImage: TImage; itsText: TText): TClearTextCmd;

        PROCEDURE TClearTextCmd.Free; OVERRIDE;
        {$IFC fParaTrace}
        PROCEDURE TClearTextCmd.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}
      {Command Execution}
        PROCEDURE TClearTextCmd.Commit; OVERRIDE;
        PROCEDURE TClearTextCmd.Perform(cmdPhase: TCmdPhase); OVERRIDE;
        END;

    TStyleCmd = SUBCLASS OF TCommand

      {Variables}
        text:		    TText;
        textSelection:	    TTextSelection;
        firstFiltParaIndex: LONGINT;
        lastFiltParaIndex:  LONGINT;
        filtFirstLP:	    INTEGER;
        filtLastLP:	    INTEGER;
        currFilteredPara:   TEditPara;	    {handle to most recently filtered paragraph}
        filteredStyles:	    TArray;	    {changed type styles of most recently filtered paragraph}

      {Creation}
        FUNCTION  TStyleCmd.CREATE(object: TObject; heap: THeap; itsCmdNumber: TCmdNumber;
                                itsImage: TImage;
                                itsFirstIndex: LONGINT; itsLastIndex:  LONGINT;
                                itsLPFirst: INTEGER; itsLPLast: INTEGER;
                                itsSelection: TTextSelection): TStyleCmd;

        PROCEDURE TStyleCmd.Free; OVERRIDE;
        {$IFC fParaTrace}
        PROCEDURE TStyleCmd.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}
      {Command Execution}
        PROCEDURE TStyleCmd.Commit; OVERRIDE;
        PROCEDURE TStyleCmd.FilterAndDo(actualObject: TObject;
                                        PROCEDURE DoToObject(filteredObject: TObject)); OVERRIDE;
        PROCEDURE TStyleCmd.Perform(cmdPhase: TCmdPhase); OVERRIDE;
        END;

    TTextCutCopy = SUBCLASS OF TCutCopyCommand

      {Variables}
        text:   TText;

      {Creation}
        FUNCTION  TTextCutCopy.CREATE(object: TObject; heap: THeap; itsCmdNumber: TCmdNumber;
                                     itsImage: TImage;
                                    isCutCmd: BOOLEAN; itsText: TText): TTextCutCopy;

        PROCEDURE TTextCutCopy.Free; OVERRIDE;
        {$IFC fParaTrace}
        PROCEDURE TTextCutCopy.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}
      {Command Execution}
        PROCEDURE TTextCutCopy.DoCutCopy(clipSelection: TSelection; deleteOriginal: BOOLEAN;
                                            cmdPhase: TCmdPhase); OVERRIDE;
        END;

    TTextPaste = SUBCLASS OF TPasteCommand

      {Variables}
        savedText:  TText;
        pasteRange: TTextRange;	    {The text range spanned by the pasted text}
        text:	    TText;
        origIsPara: BOOLEAN;
        origIsWord: BOOLEAN;
        clipIsPara: BOOLEAN;

      {Creation}
        FUNCTION  TTextPaste.CREATE(object: TObject; heap: THeap;  itsImage: TImage;
                                      itsText: TText): TTextPaste;

        PROCEDURE TTextPaste.Free; OVERRIDE;
        {$IFC fParaTrace}
        PROCEDURE TTextPaste.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}
      {Command Execution}
        PROCEDURE TTextPaste.Commit; OVERRIDE;
        PROCEDURE TTextPaste.DoPaste(clipSelection: TSelection; pic: PicHandle; cmdPhase: TCmdPhase);
                                                                                            OVERRIDE;
        END;


    TTypingCmd = SUBCLASS OF TCommand

      {Variables}
        savedText:	    TText;
        text:		    TText;
        newCharCount:	    INTEGER;
        newParaCount:	    INTEGER;
        typingRange:	    TTextRange;	    {The text range spanned by the typed characters}
        otherInsPts:	    TList;

      {Creation}
        FUNCTION  TTypingCmd.CREATE(object: TObject; heap: THeap; itsImage: TImage;
                                      itsText: TText): TTypingCmd;

        PROCEDURE TTypingCmd.Free; OVERRIDE;
        {$IFC fParaTrace}
        PROCEDURE TTypingCmd.Fields(PROCEDURE Field(nameAndType: S255)); OVERRIDE;
        {$ENDC}
      {Command Execution}
        PROCEDURE TTypingCmd.Commit; OVERRIDE;
        PROCEDURE TTypingCmd.Perform(cmdPhase: TCmdPhase); OVERRIDE;
        END;


VAR fParaTrace:		    BOOLEAN;
    fTextTrace:		    BOOLEAN;


IMPLEMENTATION

(*
{$I UTEXT2.text}  {Paragraph classes}
{$I UTEXT3.text}  {TStyleSheet, TText, TTextImage, TTextView}
{$I UTEXT4.text}  {Text Selections and Commands}
*)

{$I LibTK/UTEXT2.text}  {Paragraph classes}
{$I LibTK/UTEXT3.text}  {TStyleSheet, TText, TTextImage, TTextView}
{$I LibTK/UTEXT4.text}  {Text Selections and Commands}
END.

